/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package de.pitkley.jocabulary;

import java.io.*;
import java.util.*;

import javax.xml.parsers.*;
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;

/**
 *
 * @author pit
 */
public class Jocabulary_Controller extends DefaultHandler {

    private static final String baseURL = "http://jocabulary.pitkley.de/data/";
    private static final File workingDirectory = new File(Util.getWorkingDirectory("jocabulary"), "data/");
    private Jocabulary_GUI theGUI;
    private FileDownloader fd = new FileDownloader(baseURL, workingDirectory);
    private ArrayList<Language> languages = new ArrayList<Language>();
    private AskUnits askUnits;
    private Vocable currentVocable;
    private boolean answerShowing;
    private boolean listDone;
    private int totalCorrect;
    private int totalWrong;
    private Random r = new Random();
    private int randomOrder;
    private int settingOrder; // 0 = Random, 1 = Native->Other, 2 = Other->Native
    private String tempVal;
    private String tempItemName;
    private int tempRevision;
    private String tempItemSetName;
    private String tempSetName;
    private Language tempLang;

    public Jocabulary_Controller() {
        theGUI = new Jocabulary_GUI(this);
        theGUI.setVisible(true);

        if (!workingDirectory.isDirectory()) {
            workingDirectory.mkdirs();
        }

        fd.downloadFile("files.xml");
        parseLanguages();
        updateLanguages();
    }

    private void updateLanguages() {
        theGUI.clearLanguages();

        for (Language l : languages) {
            theGUI.addLanguage(l);
        }
    }

    private void parseLanguages() {
        SAXParserFactory spf = SAXParserFactory.newInstance();

        try {
            SAXParser sp = spf.newSAXParser();
            sp.parse(workingDirectory.getAbsolutePath() + "/files.xml", this);
        } catch (Exception e) {
            System.out.println(e);
        }
    }

    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        tempVal = "";
        tempItemName = "";

        if (qName.equalsIgnoreCase("Language")) {
            tempLang = new Language(attributes.getValue("name"), attributes.getValue("cleanname"));
        } else if (qName.equalsIgnoreCase("Item")) {
            tempItemName = attributes.getValue("name");
            tempRevision = Integer.parseInt(attributes.getValue("revision"));
            tempItemSetName = attributes.getValue("set");
        } else if (qName.equalsIgnoreCase("Set")) {
            tempSetName = attributes.getValue("name");
        }
    }

    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        tempVal = new String(ch, start, length);
    }

    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
        if (qName.equalsIgnoreCase("Language")) {
            languages.add(tempLang);
        } else if (qName.equalsIgnoreCase("Item")) {
            try {
                tempLang.addUnit(tempItemName, tempVal, tempRevision, tempItemSetName);
            } catch (IOException e) {
                System.out.println(e);
            }
        } else if (qName.equalsIgnoreCase("Set")) {
            tempLang.addSet(tempSetName, tempVal);
        }
    }

    public void start(Language language, Object[] pUnits, int pOrder, int pTimesCorrect, boolean pRequired, boolean pRandomAskOrder) {
        List<Unit> units = new ArrayList<Unit>();
        for (Object o : pUnits) {
            units.add((Unit) o);
        }

        theGUI.enableAskAndStats(true);
        theGUI.listDone(false);

        settingOrder = pOrder;
        totalCorrect = 0;
        totalWrong = 0;

        askUnits = new AskUnits(units, pTimesCorrect, pRequired, pRandomAskOrder);

        theGUI.setProgress(askUnits.getAskedCount(), askUnits.getStartSize());
        askNextVocable();
    }

    public void actionPerformed(String pTranslation) {
        if (answerShowing) {
            askNextVocable();
        } else {
            validateAnswer(pTranslation);
        }
    }

    public void askNextVocable() {
        try {
            currentVocable = askUnits.getNextVocable();
            answerShowing = false;

            if (settingOrder == 0) {
                randomOrder = r.nextInt(2) + 1;
            } else {
                randomOrder = settingOrder;
            }

            if (randomOrder == 1) { // Native->Other
                theGUI.askVocable(currentVocable.getRandomNativeWord());
            } else if (randomOrder == 2) { // Other->Native
                theGUI.askVocable(currentVocable.getRandomTranslation());
            }
            theGUI.setStats(currentVocable.getTimesCorrect(), totalCorrect, totalWrong);
        } catch (NoSuchElementException e) { // Random
            done();
        }
    }

    public void validateAnswer(String pTranslation) {
        answerShowing = true;

        if (randomOrder == 1) { // Native->Other
            if (currentVocable.verifyTranslation(pTranslation)) {
                currentVocable.answer(true);
                theGUI.answerCorrect();
                totalCorrect++;
            } else {
                currentVocable.answer(false);
                theGUI.answerWrong(currentVocable.getRandomTranslation());
                totalWrong++;
            }
        } else if (randomOrder == 2) { // Other->Native
            if (currentVocable.verifyNativeWord(pTranslation)) {
                currentVocable.answer(true);
                theGUI.answerCorrect();
                totalCorrect++;
            } else {
                currentVocable.answer(false);
                theGUI.answerWrong(currentVocable.getRandomNativeWord());
                totalWrong++;
            }
        }
        theGUI.setStats(currentVocable.getTimesCorrect(), totalCorrect, totalWrong);
        theGUI.setProgress(askUnits.getAskedCount(), askUnits.getStartSize());
    }

    private void done() {
        listDone = true;
        stop();
    }

    public void stop() {
        if (listDone) {
            theGUI.listDone(true);
            listDone = false;
        }
        askUnits.writeFiles();
        theGUI.clearFields();
        theGUI.tbtnStartSetSelected(false);
        theGUI.enableAskAndStats(false);
        theGUI.setProgress(0, 0);
    }

    public static void main(String... args) {
        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {
                new Jocabulary_Controller();
            }
        });
    }
}
